// Status.java
// Jim Sproch
// Created: April 29, 2006
// Modified: February 20, 2008
// Part of the Aforce Port
// Mac < Windows < Linux

/**
	Status gives information such as health, sheld, and damage
	@author Jim Sproch
	@version 0.1a beta
*/


public class Status
{
	private int health = 1;
	private int lives = 0;
	private int damage = 1;
	private int shield;

	AbstractObject owner;

	Status(AbstractObject owner)
	{
		this.owner = owner;
	}

	Status(int health)
	{
		this.health = health;
		damage = 1;
		shield = 0;
	}


	Status()
	{
		health = 1;
		damage = 1;
		shield = 0;
	}


	Status(int health, int damage)
	{
		this.health = health;
		this.damage = damage;
		shield = 0;
	}


	Status(int health, int damage, int shield)
	{
		this.health = health;
		this.damage = damage;
		this.shield = shield;
	}

	public void setOwner(AbstractObject owner)
	{
		this.owner = owner;
	}

	public void setLives(int lives)
	{
		this.lives = lives;
	}

	public int getLives()
	{
		return lives;
	}

	public int getShield()
	{
		return shield;
	}

	private void useLife()
	{
		if(this.health == 0 && this.lives > 0)
		{
			lives--;
			this.health = 1;
			AForce.getDashboard().update();
		}

		if(this.health == 0 && owner != null) owner.destroy();
	}

	@Deprecated
	public int gethealth()
	{
		return getHealth();
	}

	public int getHealth()
	{
	//	if(health == 0) (new Exception()).printStackTrace();
		return health;
	}

	@Deprecated
	public int getdamage()
	{
		return damage;
	}

	public int getDamage()
	{
		return damage;
	}

	public void setHealth(int health)
	{
		if(this.health == 0) return;
		this.health = health;
		if(this.health == 0) useLife();
	}

	public void takedamage(int damage)
	{
		if(this.health == 0) return;
		if(health == -1) return;

		if(damage > health) health = 0;
		else health = health - damage;

		if(this.health == 0) useLife();
	}

	public void destroy()
	{
		health = 0;
		shield = 0;
		damage = 0;
	}

	public static void main(String[] args)
	{
		Printer.noexecute();
	}


	public static void collision(AbstractObject object1, AbstractObject object2)
	{
		collision(AForce.field, object1, object2);
	}

	public static void collision(AForceEnv field, AbstractObject object1, AbstractObject object2)
	{
		// Prevents a collision being handled twice (double dipping)
		boolean actiontaken = false;

		// Deal with lasers
		if(object1 instanceof Laser || object2 instanceof Laser)
		{
			actiontaken = true;

			if(object2 instanceof Ship)
				((Laser)object1).hit(object2);
			if(object1 instanceof Ship)
				((Laser)object2).hit(object1);
		}

		if(object1.getTeam() != object2.getTeam())
		{

			// Deal with mines
			if(object1 instanceof Mine || object2 instanceof Mine)
			{
				if(object2 instanceof Ship) object2.getStatus().takedamage(object1.getStatus().getdamage());
				if(object1 instanceof Ship) object1.getStatus().takedamage(object2.getStatus().getdamage());
				if(object2 instanceof Bullet) object1.getStatus().takedamage(object2.getStatus().getdamage());
				if(object1 instanceof Bullet) object2.getStatus().takedamage(object1.getStatus().getdamage());

				// The mines should be destroyed after damage is inflicted on ships
				if(object1 instanceof Mine) object1.destroy();
				if(object2 instanceof Mine) object2.destroy();

				actiontaken = true;
			}

			//Check and deal with a hit with a block
			if(object1 instanceof Block || object2 instanceof Block)
			{
				actiontaken = true;

				AbstractObject object = null;
				if(object1 instanceof Block && !(object2 instanceof Block))
					object = object2;
				if(!(object1 instanceof Block) && object2 instanceof Block)
					object = object1;

				if(object == null) return;
				
				if(object instanceof Bullet) ((Bullet)object).destroy();
				if(object instanceof Ship) ((Ship)object).stop(5);
				return;
			}


			if(object1 instanceof Bullet && object2 instanceof Bullet)
			{
				actiontaken = true;

				// If the bullets are not flying straight at eachother
				if(((MovableObject)object1).getDirection()!=Direction.reverse(((MovableObject)object2).getDirection()))
				{
					// Find the newer bullet and add lots of points to the shooter's score
					Bullet newerBullet = ((Bullet)object1).getBirthday() > ((Bullet)object2).getBirthday() ?
						(Bullet)object1 : (Bullet)object2;
					field.addPoints(newerBullet.getTeam(), 1000); // Award points and a life to the shooter
					newerBullet.getOwner().getStatus().setLives(newerBullet.getOwner().getStatus().getLives()+1);
					if(Ship.getUserShip().getTeam() == newerBullet.getTeam()) // If it's the player's team
						AForce.getDashboard().update(); //update the score board
				}
				actiontaken = true;

				object1.destroy();
				object2.destroy();
	
			}



			if(!actiontaken)
			{
				object1.getStatus().takedamage(object2.getStatus().getdamage());
				object2.getStatus().takedamage(object1.getStatus().getdamage());
			}

			// Destroy dead objects and award points
			cleanup(field, object1, object2);

			return;
		}

		// If the two objects are not on the same team, they will never get to here!

		if(object1 instanceof Ship && object2 instanceof Ship)
		{
			((Ship)object1).reverse();
			((Ship)object2).reverse();
		}

		cleanup(field, object1, object2);

		return;
	}


	public static void cleanup(AForceEnv field, AbstractObject object1, AbstractObject object2)
	{

		if(object1.getStatus().gethealth() == 0)
		{
			if(object1 instanceof Laser) return;

			if(object1.getTeam() != object2.getTeam())  // we only award points to enemy kills
				if(object1 instanceof Ship) field.addPoints(object2.getTeam(), 100); // only award points for ships
				AForce.getDashboard().update(); // only update if we award points
			object1.destroy();
		}

		if(object2.getStatus().getHealth() == 0)
		{
			if(object2 instanceof Laser) return;
			if(object1.getTeam() != object2.getTeam())  // we only award points to enemy kills
				if(object2 instanceof Ship) field.addPoints(object1.getTeam(), 100); // only award points for ships
				AForce.getDashboard().update(); // only update if we award points
			object2.destroy();
		}

	}
}